import com.smbms.test.User;
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 反射
 * 在程序的运行期间，动态获取类的信息
 */
public class Demo {

    //通过反射创建对象
    @Test
    public void test1() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //获取类的模版 Class-用于描述其它类
        Class aClass = Class.forName("com.smbms.test.User");
        //实例化对象
        Object obj = aClass.newInstance();

        User user = (User) obj;
        user.show();
    }

    //获取属性
    @Test
    public void test2() throws Exception {
        //获取类的模版 Class-用于描述其它类
        Class aClass = User.class;

        //获取指定的属性
        Field gender = aClass.getField("gender");
        System.out.println(gender);

        System.out.println("-------------");

        //获取所有属性
        Field[] fields = aClass.getFields();
        for(Field field : fields){
            System.out.println(field);
        }
    }

    //获取方法
    @Test
    public void test3() throws Exception {
        //获取类的模版 Class-用于描述其它类
        User user = new User();
        Class aClass = user.getClass();

        //获取指定的方法
        Method getGender = aClass.getMethod("getGender");
        System.out.println(getGender);

        System.out.println("-------获取当前类的方法------");
        Method[] methods = aClass.getDeclaredMethods();
        for(Method method : methods){
            System.out.println(method);
        }

        System.out.println("-------获取当前类的方法，以及继承到的方法------");
        Method[] methods2 = aClass.getMethods();
        for(Method method : methods2){
            System.out.println(method);
        }
    }

    //调用方法
    @Test
    public void test4() throws Exception {
        //获取类的模版 Class-用于描述其它类
        Class aClass = User.class;
        
        //创建对象
        Object obj = aClass.newInstance();

        //获取方法
        Method setGender = aClass.getMethod("setGender", int.class);
        //调用方法
        Object invoke = setGender.invoke(obj, 1);
        System.out.println("返回值："+invoke);
        System.out.println(obj);

        System.out.println("-----------");

        //调用封装的方法
        Method play = aClass.getDeclaredMethod("play");
        //将方法设置为可访问
        play.setAccessible(true);

        play.invoke(obj);
    }
}
